home *** CD-ROM | disk | FTP | other *** search
/ Delphi 5 for Professionals / DELPHI5.iso / AddOns / Components / Orpheus v3.02 / SETUP.EXE / %MAINDIR% / OvcDbDat.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-02-25  |  15.7 KB  |  629 lines

  1. {*********************************************************}
  2. {*                  OVCDBDAT.PAS 3.00                    *}
  3. {*     Copyright (c) 1995-99 TurboPower Software Co      *}
  4. {*                 All rights reserved.                  *}
  5. {*********************************************************}
  6.  
  7. {$I OVC.INC}
  8.  
  9. {$B-} {Complete Boolean Evaluation}
  10. {$I+} {Input/Output-Checking}
  11. {$P+} {Open Parameters}
  12. {$T-} {Typed @ Operator}
  13. {$W-} {Windows Stack Frame}
  14. {$X+} {Extended Syntax}
  15.  
  16. {$IFNDEF Win32}
  17. {$G+} {286 Instructions}
  18. {$N+} {Numeric Coprocessor}
  19.  
  20. {$C MOVEABLE,DEMANDLOAD,DISCARDABLE}
  21. {$ENDIF}
  22.  
  23. unit OvcDbDat;
  24.   {-Data aware date edit field w/ popup calendar}
  25.  
  26. interface
  27.  
  28. uses
  29.   {$IFDEF Win32} Windows, {$ELSE} WinTypes, WinProcs, {$ENDIF}
  30.   Classes, Controls, Db, DbConsts, DbCtrls, {$IFNDEF VERSION3} DbTables, {$ENDIF}
  31.   Forms, Graphics,
  32.   Menus, Messages, StdCtrls, SysUtils,
  33.   OvcBase, OvcCal, OvcEdCal, OvcEdPop, OvcEditF;
  34.  
  35. type
  36.   TOvcCustomDbDateEdit = class(TOvcCustomDateEdit)
  37.   {.Z+}
  38.   protected {private}
  39.     FAlignment    : TAlignment;
  40.     FAutoUpdate   : Boolean;
  41.     FCanvas       : TControlCanvas;
  42.     FDataLink     : TFieldDataLink;
  43.     FFocused      : Boolean;
  44.     FPreserveTime : Boolean;
  45.  
  46.     {property methods}
  47.     function GetDataField : string;
  48.     function GetDataSource : TDataSource;
  49.     function GetField : TField;
  50.     function GetReadOnly : Boolean;
  51.     procedure SetDataField(const Value : string);
  52.     procedure SetDataSource(Value : TDataSource);
  53.     procedure SetFocused(Value : Boolean);
  54.     procedure SetReadOnly(Value : Boolean);
  55.  
  56.     {internal methods}
  57.     procedure DataChange(Sender : TObject);
  58.     procedure EditingChange(Sender : TObject);
  59.     function  GetTextMargins : TPoint;
  60.     procedure UpdateData(Sender : TObject);
  61.  
  62.     {message methods}
  63.     procedure WMCut(var Message : TMessage);
  64.       message WM_CUT;
  65.     procedure WMPaste(var Message : TMessage);
  66.       message WM_PASTE;
  67.     procedure WMPaint(var Message : TWMPaint);
  68.       message WM_PAINT;
  69.     procedure CMEnter(var Message : TCMEnter);
  70.       message CM_ENTER;
  71.     procedure CMExit(var Message : TCMExit);
  72.       message CM_EXIT;
  73.     {$IFDEF Win32}
  74.     procedure CMGetDataLink(var Message : TMessage);
  75.       message CM_GETDATALINK;
  76.     {$ENDIF Win32}
  77.  
  78.   protected
  79.     procedure Change;
  80.       override;
  81.     function GetButtonEnabled : Boolean;
  82.       override;
  83.     procedure KeyDown(var Key : Word; Shift : TShiftState);
  84.       override;
  85.     procedure KeyPress(var Key : Char);
  86.       override;
  87.     procedure Notification(AComponent : TComponent; Operation : TOperation);
  88.       override;
  89.   {.Z-}
  90.  
  91.     {protected properties}
  92.     property AutoUpdate : Boolean
  93.       read FAutoUpdate write FAutoUpdate;
  94.     property DataField : string
  95.       read GetDataField write SetDataField;
  96.     property DataSource : TDataSource
  97.       read GetDataSource write SetDataSource;
  98.     property PreserveTime : Boolean
  99.       read FPreserveTime write FPreserveTime;
  100.  
  101.   {.Z+}
  102.     property ReadOnly : Boolean {hides ancestor's ReadOnly property}
  103.       read GetReadOnly
  104.       write SetReadOnly;
  105.  
  106.   public
  107.     constructor Create(AOwner : TComponent);
  108.       override;
  109.     destructor Destroy;
  110.       override;
  111.     {$IFDEF VERSION4}
  112.     function ExecuteAction(Action: TBasicAction): Boolean;
  113.       override;
  114.     function UpdateAction(Action: TBasicAction): Boolean;
  115.       override;
  116.     {$ENDIF}
  117.  
  118.     procedure PopupClose(Sender : TObject);
  119.       override;
  120.     procedure PopupOpen;
  121.       override;
  122.   {.Z-}
  123.  
  124.     {public properties}
  125.     property Field : TField
  126.       read GetField;
  127.   end;
  128.  
  129.   TOvcDbDateEdit = class(TOvcCustomDbDateEdit)
  130.   published
  131.     {properties}
  132.     {$IFDEF VERSION4}
  133.     property Anchors;
  134.     property Constraints;
  135.     property DragKind;
  136.     {$ENDIF}
  137.     property About;
  138.     property AllowIncDec;
  139.     property AutoSelect;
  140.     property AutoSize;
  141.     property AutoUpdate;
  142.     property BorderStyle;
  143.     property ButtonGlyph;
  144.     property CharCase;
  145.     property Color;
  146.     property Controller;
  147.     property Ctl3D;
  148.     property Cursor;
  149.     property DataField;
  150.     property DataSource;
  151.     property DragCursor;
  152.     property DragMode;
  153.     property Enabled;
  154.     property Epoch;
  155.     property Font;
  156.     property ForceCentury;
  157.     property HideSelection;
  158.     property LabelInfo;
  159.     property ParentColor;
  160.     property ParentCtl3D;
  161.     property ParentFont;
  162.     property ParentShowHint;
  163.     property PopupAnchor;
  164.     property PopupColors;
  165.     property PopupDateFormat;
  166.     property PopupDayNameWidth;
  167.     property PopupFont;
  168.     property PopupHeight;
  169.     property PopupMenu;
  170.     property PopupOptions;
  171.     property PopupWidth;
  172.     property PopupWeekStarts;
  173.     property PreserveTime;
  174.     property ReadOnly;
  175.     property RequiredFields;
  176.     property ShowButton;
  177.     property ShowHint;
  178.     property TabOrder;
  179.     property TabStop;
  180.     property TodayString;
  181.     property Visible;
  182.  
  183.     {inherited events}
  184.     property OnChange;
  185.     property OnClick;
  186.     property OnDblClick;
  187.     property OnDragDrop;
  188.     property OnDragOver;
  189.     property OnEndDrag;
  190.     property OnEnter;
  191.     property OnExit;
  192.     property OnGetDate;
  193.     property OnKeyDown;
  194.     property OnKeyPress;
  195.     property OnKeyUp;
  196.     property OnMouseDown;
  197.     property OnMouseMove;
  198.     property OnMouseUp;
  199.     property OnSetDate;
  200.     {$IFDEF Win32}
  201.     property OnStartDrag;
  202.     {$ENDIF Win32}
  203.   end;
  204.  
  205.  
  206. implementation
  207.  
  208. const
  209.   DateFieldTypes : set of  TFieldType = [ftDate, ftDateTime];
  210.  
  211.  
  212. {*** TOvcCustomDbDateEdit ***}
  213.  
  214. procedure TOvcCustomDbDateEdit.Change;
  215. begin
  216.   FDataLink.Modified;
  217.  
  218.   inherited Change;
  219. end;
  220.  
  221. procedure TOvcCustomDbDateEdit.CMEnter(var Message : TCMEnter);
  222. begin
  223.   SetFocused(True);
  224.  
  225.   inherited;
  226. end;
  227.  
  228. procedure TOvcCustomDbDateEdit.CMExit(var Message : TCMExit);
  229. var
  230.   WasModified : Boolean;
  231. begin
  232.   if PopupActive then
  233.     Exit;
  234.  
  235.   if AutoUpdate then begin
  236.     WasModified := Modified;
  237.     DoExit;    {force update of date}
  238.     try
  239.       if WasModified then
  240.         FDataLink.UpdateRecord;
  241.     except
  242.       SelectAll;
  243.       SetFocus;
  244.       raise;
  245.     end;
  246.   end;
  247.   SetFocused(False);
  248. end;
  249.  
  250. {$IFDEF Win32}
  251. procedure TOvcCustomDbDateEdit.CMGetDataLink(var Message : TMessage);
  252. begin
  253.   Message.Result := LongInt(FDataLink);
  254. end;
  255. {$ENDIF Win32}
  256.  
  257. constructor TOvcCustomDbDateEdit.Create(AOwner : TComponent);
  258. begin
  259.   inherited Create(AOwner);
  260.  
  261.   inherited ReadOnly := True;
  262.  
  263.   {$IFDEF Win32}
  264.   ControlStyle := ControlStyle + [csReplicatable];
  265.   {$ENDIF Win32}
  266.  
  267.   FAutoUpdate := True;
  268.   FDataLink := TFieldDataLink.Create;
  269.   FDataLink.Control := Self;
  270.   FDataLink.OnDataChange := DataChange;
  271.   FDataLink.OnEditingChange := EditingChange;
  272.   FDataLink.OnUpdateData := UpdateData;
  273. end;
  274.  
  275. procedure TOvcCustomDbDateEdit.DataChange(Sender : TObject);
  276. var
  277.   P  : Integer;
  278.   DT : TDateTime;
  279.   S  : string[80];
  280. begin
  281.   if FDataLink.Field <> nil then begin
  282.     if FAlignment <> FDataLink.Field.Alignment then begin
  283.       FAlignment := FDataLink.Field.Alignment;
  284.       Text := '';
  285.     end;
  286.     if FDataLink.Field.DataType in DateFieldTypes then begin
  287.       if FDataLink.Field.IsNull then
  288.         Text := ''
  289.       else begin
  290.         DT := FDataLink.Field.AsDateTime;
  291.         SetDate(Trunc(DT))
  292.       end;
  293.     end else if FDataLink.Field.DataType = ftFloat then begin
  294.       if FDataLink.Field.IsNull then
  295.         Text := ''
  296.       else begin
  297.         DT := FDataLink.Field.AsFloat;
  298.         SetDate(Trunc(DT))
  299.       end;
  300.     end else begin
  301.       S := FDataLink.Field.ClassName;
  302.       S[1] := '(';
  303.       P := Pos('Field', S);
  304.       if P > 0 then begin
  305.         S[P] := ')';
  306.         S[0] := Char(P);
  307.       end else
  308.         S := Concat(S, ')');
  309.       Text := S;
  310.     end;
  311.   end else begin
  312.     FAlignment := taLeftJustify;
  313.     if csDesigning in ComponentState then
  314.       Text := Name
  315.     else
  316.       Text := '';
  317.   end;
  318. end;
  319.  
  320. destructor TOvcCustomDbDateEdit.Destroy;
  321. begin
  322.   FDataLink.Free;
  323.   FDataLink := nil;
  324.  
  325.   FCanvas.Free;
  326.   FCanvas := nil;
  327.  
  328.   inherited Destroy;
  329. end;
  330.  
  331. procedure TOvcCustomDbDateEdit.EditingChange(Sender : TObject);
  332. begin
  333.   inherited ReadOnly := not FDataLink.Editing;
  334.  
  335.   FButton.Enabled := GetButtonEnabled;
  336. end;
  337.  
  338. function TOvcCustomDbDateEdit.GetButtonEnabled : Boolean;
  339. begin
  340.   Result := (FDataLink <> nil) and (FDataLink.DataSource <> nil) and
  341.     (FDataLink.Editing or FDataLink.DataSource.AutoEdit) or
  342.     (csDesigning in ComponentState);
  343. end;
  344.  
  345. function TOvcCustomDbDateEdit.GetDataField : string;
  346. begin
  347.   Result := FDataLink.FieldName;
  348. end;
  349.  
  350. function TOvcCustomDbDateEdit.GetDataSource : TDataSource;
  351. begin
  352.   Result := FDataLink.DataSource;
  353. end;
  354.  
  355. function TOvcCustomDbDateEdit.GetField : TField;
  356. begin
  357.   Result := FDataLink.Field;
  358. end;
  359.  
  360. function TOvcCustomDbDateEdit.GetReadOnly : Boolean;
  361. begin
  362.   Result := FDataLink.ReadOnly;
  363.   if FDataLink.Field <> nil then
  364.     if not ((FDataLink.Field.DataType in DateFieldTypes) or
  365.             (FDataLink.Field.DataType= ftFloat)) then
  366.       Result := True;
  367. end;
  368.  
  369. function TOvcCustomDbDateEdit.GetTextMargins : TPoint;
  370. var
  371.   DC         : HDC;
  372.   SaveFont   : HFont;
  373.   I          : Integer;
  374.   SysMetrics : TTextMetric;
  375.   Metrics    : TTextMetric;
  376. begin
  377.   if NewStyleControls then begin
  378.     if BorderStyle = bsNone then
  379.       I := 0
  380.     else if Ctl3D then
  381.       I := 1
  382.     else
  383.       I := 2;
  384.     {$IFDEF Win32}
  385.     Result.X := SendMessage(Handle, EM_GETMARGINS, 0, 0) and $0000FFFF + I;
  386.     {$ELSE}
  387.     Result.X := 2;
  388.     {$ENDIF Win32}
  389.     Result.Y := I;
  390.   end else begin
  391.     if BorderStyle = bsNone then
  392.       I := 0
  393.     else begin
  394.       DC := GetDC(0);
  395.       GetTextMetrics(DC, SysMetrics);
  396.       SaveFont := SelectObject(DC, Font.Handle);
  397.       GetTextMetrics(DC, Metrics);
  398.       SelectObject(DC, SaveFont);
  399.       ReleaseDC(0, DC);
  400.       I := SysMetrics.tmHeight;
  401.       if I > Metrics.tmHeight then
  402.         I := Metrics.tmHeight;
  403.       I := I div 4;
  404.     end;
  405.     Result.X := I;
  406.     Result.Y := I;
  407.   end;
  408. end;
  409.  
  410. procedure TOvcCustomDbDateEdit.KeyDown(var Key : Word; Shift : TShiftState);
  411. begin
  412.   inherited KeyDown(Key, Shift);
  413.  
  414.   {start edit mdoe if cutting or pasting}
  415.   if (Key = VK_DELETE) or ((Key = VK_INSERT) and (ssShift in Shift)) then
  416.     FDataLink.Edit;
  417. end;
  418.  
  419. procedure TOvcCustomDbDateEdit.KeyPress(var Key : Char);
  420. begin
  421.   if AllowIncDec and (Key in ['+', '-']) then
  422.     FDataLink.Edit;
  423.  
  424.   inherited KeyPress(Key);
  425.  
  426.   if (Key in [#32..#255]) and (FDataLink.Field <> nil) and
  427.      not FDataLink.Field.IsValidChar(Key) then begin
  428.     MessageBeep(0);
  429.     Key := #0;
  430.   end;
  431.  
  432.   case Key of
  433.     ^H, ^V, ^X, #32..#255 :
  434.       FDataLink.Edit;
  435.     #27:
  436.       begin
  437.         FDataLink.Reset;
  438.         SelectAll;
  439.         Key := #0;
  440.       end;
  441.   end;
  442. end;
  443.  
  444. procedure TOvcCustomDbDateEdit.Notification(AComponent : TComponent; Operation : TOperation);
  445. begin
  446.   inherited Notification(AComponent, Operation);
  447.  
  448.   if (Operation = opRemove) and (FDataLink <> nil) and (AComponent = DataSource) then
  449.     DataSource := nil;
  450. end;
  451.  
  452. procedure TOvcCustomDbDateEdit.PopupClose(Sender : TObject);
  453. begin
  454.   inherited PopupClose(Sender);
  455.  
  456.   {allow control to see focus change that was blocked when popup became active}
  457.   if not Focused then
  458.     Perform(CM_EXIT, 0, 0);
  459. end;
  460.  
  461. procedure TOvcCustomDbDateEdit.PopupOpen;
  462. begin
  463.   inherited PopupOpen;
  464.  
  465.   {enter edit mode}
  466.   FDataLink.Edit;
  467. end;
  468.  
  469. procedure TOvcCustomDbDateEdit.SetDataField(const Value : string);
  470. begin
  471.   try
  472.     FDataLink.FieldName := Value;
  473.   except
  474.     FDataLink.FieldName := '';
  475.     raise;
  476.   end;
  477. end;
  478.  
  479. procedure TOvcCustomDbDateEdit.SetDataSource(Value : TDataSource);
  480. begin
  481.   FDataLink.DataSource := Value;
  482.   {$IFDEF Win32}
  483.   if Value <> nil then
  484.     Value.FreeNotification(Self);
  485.   {$ENDIF Win32}
  486. end;
  487.  
  488. procedure TOvcCustomDbDateEdit.SetFocused(Value : Boolean);
  489. begin
  490.   if FFocused <> Value then begin
  491.     FFocused := Value;
  492.     if (FAlignment <> taLeftJustify) then
  493.       Invalidate;
  494.     FDataLink.Reset;
  495.   end;
  496. end;
  497.  
  498. procedure TOvcCustomDbDateEdit.SetReadOnly(Value : Boolean);
  499. begin
  500.   FDataLink.ReadOnly := Value;
  501. end;
  502.  
  503. procedure TOvcCustomDbDateEdit.UpdateData(Sender : TObject);
  504. var
  505.   DT : TDateTime;
  506. begin
  507.   if (FDataLink.Field.DataType in DateFieldTypes) or
  508.      (FDataLink.Field.DataType = ftFloat) then begin
  509.     if FDataLink.Field.DataType = ftFloat then
  510.       DT := FDataLink.Field.AsFloat
  511.     else
  512.       DT := FDataLink.Field.AsDateTime;
  513.     if Text = '' then begin {save just the time portion}
  514.       if FPreserveTime and (FDataLink.Field.DataType in [ftDateTime, ftFloat])
  515.         and (Frac(DT) <> 0) then begin
  516.         if FDataLink.Field.DataType = ftFloat then
  517.           FDataLink.Field.AsFloat := Frac(DT)
  518.         else
  519.           FDataLink.Field.AsDateTime := Frac(DT);
  520.       end else
  521.         FDataLink.Field.Clear;
  522.     end else begin
  523.       DoExit;  {validate field and translate date}
  524.       if FDataLink.Field.DataType = ftFloat then begin
  525.         if FPreserveTime then
  526.           FDataLink.Field.AsFloat := FDate + Frac(DT)
  527.         else
  528.           FDataLink.Field.AsFloat := FDate;
  529.       end else begin
  530.         if FPreserveTime then
  531.           FDataLink.Field.AsDateTime := FDate + Frac(DT)
  532.         else
  533.           FDataLink.Field.AsDateTime := FDate;
  534.       end;
  535.     end;
  536.   end else
  537.     FDataLink.Field.Text := Text;
  538. end;
  539.  
  540. procedure TOvcCustomDbDateEdit.WMCut(var Message : TMessage);
  541. begin
  542.   FDataLink.Edit;
  543.  
  544.   inherited;
  545. end;
  546.  
  547. procedure TOvcCustomDbDateEdit.WMPaint(var Message : TWMPaint);
  548. var
  549.   Left    : Integer;
  550.   Margins : TPoint;
  551.   R       : TRect;
  552.   DC      : HDC;
  553.   PS      : TPaintStruct;
  554.   S       : string;
  555. begin
  556.   {$IFDEF Win32}
  557.   if ((FAlignment = taLeftJustify) or FFocused) and not (csPaintCopy in ControlState) then begin
  558.   {$ELSE}
  559.   if ((FAlignment = taLeftJustify) or FFocused) then begin
  560.   {$ENDIF Win32}
  561.     inherited;
  562.     Exit;
  563.   end;
  564.  
  565.   {draw right and center justify manually unless the edit has the focus}
  566.   if FCanvas = nil then begin
  567.     FCanvas := TControlCanvas.Create;
  568.     FCanvas.Control := Self;
  569.   end;
  570.   DC := Message.DC;
  571.   if DC = 0 then
  572.     DC := BeginPaint(Handle, PS);
  573.   FCanvas.Handle := DC;
  574.   try
  575.     FCanvas.Font := Font;
  576.     with FCanvas do begin
  577.       R := ClientRect;
  578.       if not (NewStyleControls and Ctl3D) and (BorderStyle = bsSingle) then begin
  579.         Brush.Color := clWindowFrame;
  580.         FrameRect(R);
  581.         InflateRect(R, -1, -1);
  582.       end;
  583.       Brush.Color := Color;
  584.       {$IFDEF Win32}
  585.       if (csPaintCopy in ControlState) and (FDataLink.Field <> nil) then begin
  586.         S := FDataLink.Field.DisplayText;
  587.       end else
  588.       {$ENDIF Win32}
  589.         S := Text;
  590.       if PasswordChar <> #0 then FillChar(S[1], Length(S), PasswordChar);
  591.       Margins := GetTextMargins;
  592.       case FAlignment of
  593.         taLeftJustify  : Left := Margins.X;
  594.         taRightJustify : Left := ClientWidth - TextWidth(S) - Margins.X - 2 - GetButtonWidth;
  595.       else
  596.         Left := (ClientWidth - TextWidth(S)) div 2;
  597.       end;
  598.       TextRect(R, Left, Margins.Y, S);
  599.     end;
  600.   finally
  601.     FCanvas.Handle := 0;
  602.     if Message.DC = 0 then
  603.       EndPaint(Handle, PS);
  604.   end;
  605. end;
  606.  
  607. procedure TOvcCustomDbDateEdit.WMPaste(var Message : TMessage);
  608. begin
  609.   FDataLink.Edit;
  610.  
  611.   inherited;
  612. end;
  613.  
  614. {$IFDEF VERSION4}
  615. function TOvcCustomDbDateEdit.ExecuteAction(Action : TBasicAction) : Boolean;
  616. begin
  617.   Result := inherited ExecuteAction(Action) or (FDataLink <> nil) and
  618.     FDataLink.ExecuteAction(Action);
  619. end;
  620.  
  621. function TOvcCustomDbDateEdit.UpdateAction(Action : TBasicAction) : Boolean;
  622. begin
  623.   Result := inherited UpdateAction(Action) or (FDataLink <> nil) and
  624.     FDataLink.UpdateAction(Action);
  625. end;
  626. {$ENDIF}
  627.  
  628. end.
  629.